package com.thunder.ktv.scoreengine2test.ui;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicLong;

public class PitchView extends View {

    // --- 可配置常量 ---

    // 音高取值范围
    private static final int MIN_PITCH = 20;
    private static final int MAX_PITCH = 100;

    // 数据点在屏幕上保留的最大数量
    private static final int MAX_DATA_POINTS = 600;
    // 数据点之间的水平间距（像素）
    private static final float HORIZONTAL_SPACING = 1.0f;
    // 数据点的半径（像素）
    private static final float POINT_RADIUS = 2.0f;


    // --- 内部变量 ---

    private Paint pitch1Paint;
    private Paint pitch2Paint;
    private Paint guideLinePaint; // 辅助线画笔

    // 使用 LinkedList 存储音高数据，因为它在头部添加和尾部删除效率很高
    // 使用 synchronizedList 来保证线程安全
    private final LinkedList<Integer> pitch1Data = new LinkedList<>();
    private final LinkedList<Integer> pitch2Data = new LinkedList<>();

    // 构造函数
    public PitchView(Context context) {
        super(context);
        init();
    }

    public PitchView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PitchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public PitchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    /**
     * 初始化画笔等资源
     */
    private void init() {
        // 初始化第一个音高的画笔 (例如：蓝色)
        pitch1Paint = new Paint();
        pitch1Paint.setColor(Color.parseColor("#33b5e5")); // Holo Blue
        pitch1Paint.setAntiAlias(true); // 抗锯齿
        pitch1Paint.setStyle(Paint.Style.FILL);

        // 初始化第二个音高的画笔 (例如：红色)
        pitch2Paint = new Paint();
        pitch2Paint.setColor(Color.parseColor("#ff4444")); // Holo Red
        pitch2Paint.setAntiAlias(true);
        pitch2Paint.setStyle(Paint.Style.FILL);

        // 初始化辅助线画笔 (可选，用于显示音高范围)
        guideLinePaint = new Paint();
        guideLinePaint.setColor(Color.GRAY);
        guideLinePaint.setStrokeWidth(1.0f);
        guideLinePaint.setAlpha(100); // 半透明
    }

    /**
     * 外部调用的接口，用于添加新的音高数据
     * 这个方法需要是线程安全的，因为它可能从非UI线程调用
     * @param pitch1 第一个音高值
     * @param pitch2 第二个音高值
     */
    public void addPatch(int pitch1, int pitch2) {
        // 使用 synchronized 块来确保对列表的并发访问是安全的
        synchronized (pitch1Data) {
            // 将新数据添加到列表头部
            pitch1Data.addFirst(pitch1);
            // 如果列表超过最大长度，则移除最旧的数据（在列表尾部）
            if (pitch1Data.size() > MAX_DATA_POINTS) {
                pitch1Data.removeLast();
            }
        }

        synchronized (pitch2Data) {
            pitch2Data.addFirst(pitch2);
            if (pitch2Data.size() > MAX_DATA_POINTS) {
                pitch2Data.removeLast();
            }
        }

        // 请求重绘View。postInvalidate()是线程安全的，可以从任何线程调用。
        postInvalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int viewWidth = getWidth();
        int viewHeight = getHeight();

        // 1. 绘制背景 (可选)
        canvas.drawColor(Color.BLACK);

        // 2. 绘制辅助线 (可选，显示音高范围)
        float yForMinPitch = mapPitchToY(MIN_PITCH);
        float yForMaxPitch = mapPitchToY(MAX_PITCH);
        canvas.drawLine(0, yForMinPitch, viewWidth, yForMinPitch, guideLinePaint);
        canvas.drawLine(0, yForMaxPitch, viewWidth, yForMaxPitch, guideLinePaint);


        // 3. 绘制第一个音高序列
        drawPitchPath(canvas, pitch1Data, pitch1Paint, viewWidth);

        // 4. 绘制第二个音高序列
        drawPitchPath(canvas, pitch2Data, pitch2Paint, viewWidth);
    }

    /**
     * 封装的绘制路径方法
     * @param canvas 画布
     * @param data 要绘制的数据列表
     * @param paint 使用的画笔
     * @param viewWidth 视图宽度
     */
    private void drawPitchPath(Canvas canvas, LinkedList<Integer> data, Paint paint, int viewWidth) {
        synchronized (data) {
            for (int i = 0; i < data.size(); i++) {
                Integer pitch = data.get(i);

                // 计算X坐标：最新的点(i=0)在最右边，随着i增大，点向左移动
                float x = viewWidth - i * HORIZONTAL_SPACING;

                // 如果点已经移出屏幕左侧，就不再绘制，以提高性能
                if (x < 0) {
                    break;
                }

                // 计算Y坐标
                float y = mapPitchToY(pitch);

                // 绘制圆点
                canvas.drawCircle(x, y, POINT_RADIUS, paint);
            }
        }
    }


    /**
     * 将音高值映射到View的Y坐标
     * @param pitch 音高值 (20-100)
     * @return 对应的Y坐标
     */
    private float mapPitchToY(int pitch) {
        int viewHeight = getHeight();
        float pitchRange = MAX_PITCH - MIN_PITCH;

        // 首先，将pitch值限制在我们的范围内，防止异常值导致绘制出界
        int clampedPitch = Math.max(MIN_PITCH, Math.min(pitch, MAX_PITCH));

        // 计算音高在范围内的归一化比例 (0.0 to 1.0)
        float normalizedPitch = (clampedPitch - MIN_PITCH) / pitchRange;

        // 将归一化比例映射到View的高度
        // Y坐标系是反的（0在顶部），所以用 viewHeight 减去计算出的高度
        return viewHeight - (normalizedPitch * viewHeight);
    }

    /**
     * 清空所有数据，重置视图
     */
    public void clear() {
        synchronized (pitch1Data) {
            pitch1Data.clear();
        }
        synchronized (pitch2Data) {
            pitch2Data.clear();
        }
        postInvalidate();
    }
}